import time
import random
import hashlib
from datetime import datetime
from typing import List, Dict, Optional

# 工具函数：加密密码
def encrypt_password(password: str) -> str:
    """使用MD5加密密码（实际应用中应使用更安全的加密方式）"""
    return hashlib.md5(password.encode()).hexdigest()

# 支付账户类
class PaymentAccount:
    """支付账户类，管理支付方式、余额和交易记录"""
    def __init__(self, account_id: str, password: str, balance: float = 0.0):
        self.account_id = account_id  # 账户ID
        self.password_hash = encrypt_password(password)  # 加密后的密码
        self.balance = balance  # 账户余额
        self.transaction_history: List[Dict] = []  # 交易记录

    def verify_password(self, password: str) -> bool:
        """验证支付密码"""
        return self.password_hash == encrypt_password(password)

    def deduct_balance(self, amount: float, order_number: str) -> bool:
        """扣除余额并记录交易"""
        if amount <= 0:
            return False
        if self.balance < amount:
            return False
            
        self.balance -= amount
        self.transaction_history.append({
            "order_number": order_number,
            "amount": amount,
            "type": "支出",
            "time": datetime.now()
        })
        return True

    def add_balance(self, amount: float, description: str = "充值") -> bool:
        """增加余额（充值）"""
        if amount <= 0:
            return False
            
        self.balance += amount
        self.transaction_history.append({
            "order_number": f"TOPUP{datetime.now().strftime('%Y%m%d%H%M%S')}",
            "amount": amount,
            "type": "收入",
            "description": description,
            "time": datetime.now()
        })
        return True

    def display_balance(self) -> None:
        """显示当前余额"""
        print(f"当前余额: ¥{self.balance:.2f}")

    def display_transaction_history(self, limit: int = 5) -> None:
        """显示交易记录"""
        if not self.transaction_history:
            print("暂无交易记录")
            return
            
        print("\n===== 最近交易记录 =====")
        for i, record in enumerate(reversed(self.transaction_history[:limit])):
            time_str = record["time"].strftime("%Y-%m-%d %H:%M")
            print(f"{i+1}. {time_str} - {record['type']} ¥{record['amount']:.2f}")
            print(f"   订单号: {record['order_number']}")


# 支付系统类
class PaymentSystem:
    """支付系统，管理多种支付方式"""
    def __init__(self):
        # 初始化预设支付账户（实际应用中应从数据库加载）
        self.accounts = {
            "wechat_123456": PaymentAccount("wechat_123456", "123456", 500.0),  # 微信支付账户
            "alipay_654321": PaymentAccount("alipay_654321", "654321", 800.0),   # 支付宝账户
            "card_888888": PaymentAccount("card_888888", "888888", 1000.0)       # 银行卡账户
        }
        self.payment_methods = {
            1: {"name": "微信支付", "account_id": "wechat_123456"},
            2: {"name": "支付宝", "account_id": "alipay_654321"},
            3: {"name": "银行卡", "account_id": "card_888888"}
        }

    def get_account(self, account_id: str) -> Optional[PaymentAccount]:
        """获取支付账户"""
        return self.accounts.get(account_id)

    def list_payment_methods(self) -> None:
        """列出所有支付方式"""
        print("请选择支付方式:")
        for key, method in self.payment_methods.items():
            print(f"{key}. {method['name']}")

    def process_payment(self, amount: float, order_number: str, method_choice: int) -> bool:
        """处理支付流程"""
        if method_choice not in self.payment_methods:
            print("无效的支付方式选择")
            return False

        method = self.payment_methods[method_choice]
        account = self.get_account(method["account_id"])
        
        if not account:
            print("支付账户不存在")
            return False

        # 显示账户信息（脱敏）
        print(f"\n您选择了{method['name']}，账户尾号: ****{account.account_id[-4:]}")
        
        # 验证支付密码
        password = input("请输入支付密码: ")
        if not account.verify_password(password):
            print("支付密码错误")
            return False

        # 显示余额并确认支付
        account.display_balance()
        confirm = input(f"确认支付 ¥{amount:.2f} 吗? (y/n): ")
        if confirm.lower() != 'y':
            print("已取消支付")
            return False

        # 执行支付
        print("\n正在处理支付...")
        time.sleep(1)
        
        if account.deduct_balance(amount, order_number):
            print(f"\n{method['name']}支付成功！")
            print(f"支付金额: ¥{amount:.2f}")
            account.display_balance()
            return True
        else:
            print("\n支付失败，余额不足")
            # 提供充值选项
            recharge = input("是否需要充值? (y/n): ")
            if recharge.lower() == 'y':
                try:
                    recharge_amount = float(input("请输入充值金额: "))
                    if account.add_balance(recharge_amount):
                        print(f"充值成功，当前余额: ¥{account.balance:.2f}")
                        # 尝试再次支付
                        return self.process_payment(amount, order_number, method_choice)
                except ValueError:
                    print("无效的金额输入")
            return False


# 菜单和订单相关类
class MenuItem:
    """菜单项目类，存储菜品信息"""
    def __init__(self, id, name, cuisine, category, price, description):
        self.id = id
        self.name = name
        self.cuisine = cuisine  # 菜系
        self.category = category  # 大类（中餐、西餐等）
        self.price = price
        self.description = description

    def __str__(self):
        return f"{self.id}. {self.name} - ¥{self.price:.2f} ({self.description})"


class OrderItem:
    """订单项目类，存储订单中的菜品及数量"""
    def __init__(self, menu_item, quantity=1):
        self.menu_item = menu_item
        self.quantity = quantity

    def get_total(self):
        """计算该菜品的总价"""
        return self.menu_item.price * self.quantity


class Order:
    """订单类，管理整个订单信息"""
    def __init__(self):
        self.items = []
        self.order_number = self.generate_order_number()
        self.status = "未支付"
        self.payment_method = None
        self.create_time = datetime.now()
        self.payment_time = None

    def generate_order_number(self):
        """生成唯一订单号"""
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        random_num = random.randint(1000, 9999)
        return f"ORD{timestamp}{random_num}"

    def add_item(self, menu_item, quantity=1):
        """添加菜品到订单"""
        for item in self.items:
            if item.menu_item.id == menu_item.id:
                item.quantity += quantity
                return True
        self.items.append(OrderItem(menu_item, quantity))
        return True

    def remove_item(self, item_id):
        """从订单中移除菜品"""
        for index, item in enumerate(self.items):
            if item.menu_item.id == item_id:
                del self.items[index]
                return True
        return False

    def update_quantity(self, item_id, quantity):
        """更新菜品数量"""
        if quantity <= 0:
            return self.remove_item(item_id)
            
        for item in self.items:
            if item.menu_item.id == item_id:
                item.quantity = quantity
                return True
        return False

    def get_total(self):
        """计算订单总价"""
        return sum(item.get_total() for item in self.items)

    def display_order(self):
        """显示订单详情"""
        if not self.items:
            print("您的订单是空的")
            return
            
        print("\n===== 订单详情 =====")
        for index, item in enumerate(self.items, 1):
            print(f"{index}. {item.menu_item.name} x {item.quantity} - ¥{item.get_total():.2f}")
        print("====================")
        print(f"总计: ¥{self.get_total():.2f}")


# 主应用类
class RestaurantApp:
    """餐厅点餐应用类，管理整个点餐流程"""
    def __init__(self):
        self.menu = self.initialize_menu()
        self.current_order = Order()
        self.payment_system = PaymentSystem()  # 初始化支付系统
        self.order_history: List[Order] = []  # 订单历史

    def initialize_menu(self):
        """初始化菜单，包含各大菜系和中西餐分类"""
        return [
            # 中餐 - 川菜
            MenuItem(1, "麻婆豆腐", "川菜", "中餐", 28.00, "麻辣鲜香，传统川菜"),
            MenuItem(2, "水煮鱼", "川菜", "中餐", 88.00, "麻辣可口，鱼肉鲜嫩"),
            
            # 中餐 - 粤菜
            MenuItem(3, "烧鹅", "粤菜", "中餐", 98.00, "皮脆肉嫩，经典粤式烧味"),
            MenuItem(4, "白切鸡", "粤菜", "中餐", 68.00, "原汁原味，蘸料提鲜"),
            
            # 中餐 - 鲁菜
            MenuItem(5, "九转大肠", "鲁菜", "中餐", 68.00, "酸甜苦辣咸，五味俱全"),
            
            # 西餐
            MenuItem(6, "澳洲西冷牛排", "西式", "西餐", 198.00, "三分熟，肉质鲜嫩"),
            MenuItem(7, "意大利肉酱面", "意式", "西餐", 58.00, "经典意面，肉酱浓郁"),
            
            # 饮品
            MenuItem(8, "酸梅汤", "中式", "饮品", 12.00, "传统解暑饮品"),
            MenuItem(9, "拿铁咖啡", "西式", "饮品", 32.00, "浓郁奶香，口感顺滑"),
            
            # 甜点
            MenuItem(10, "提拉米苏", "意式", "甜点", 42.00, "经典意大利甜点"),
            MenuItem(11, "双皮奶", "粤式", "甜点", 22.00, "传统粤式甜品")
        ]

    def display_menu(self, filter_type=None, filter_value=None):
        """显示菜单，可按类别筛选"""
        print("\n===== 菜单 =====")
        
        if filter_type == "category":
            filtered_menu = [item for item in self.menu if item.category == filter_value]
        elif filter_type == "cuisine":
            filtered_menu = [item for item in self.menu if item.cuisine == filter_value]
        else:
            filtered_menu = self.menu
            
        if not filtered_menu:
            print("没有找到相关菜品")
            return
            
        current_cuisine = None
        for item in filtered_menu:
            if item.cuisine != current_cuisine:
                current_cuisine = item.cuisine
                print(f"\n【{current_cuisine}】")
            print(item)
        print("================\n")

    def display_categories(self):
        """显示所有菜品大类"""
        categories = set(item.category for item in self.menu)
        print("菜品大类:")
        for i, category in enumerate(sorted(categories), 1):
            print(f"{i}. {category}")
        print(f"{len(categories)+1}. 按菜系浏览")
        print(f"{len(categories)+2}. 全部菜品")

    def display_cuisines(self):
        """显示所有菜系"""
        cuisines = set(item.cuisine for item in self.menu)
        print("菜系列表:")
        for i, cuisine in enumerate(sorted(cuisines), 1):
            print(f"{i}. {cuisine}")
        print(f"{len(cuisines)+1}. 返回上一级")

    def order_food(self):
        """点餐流程"""
        while True:
            print("\n===== 点餐 =====")
            self.display_categories()
            try:
                cat_choice = int(input("请选择要查看的类别 (输入编号): "))
                categories = sorted(set(item.category for item in self.menu))
                cuisines = sorted(set(item.cuisine for item in self.menu))
                
                if cat_choice == len(categories) + 2:
                    self.display_menu()
                elif cat_choice == len(categories) + 1:
                    while True:
                        self.display_cuisines()
                        try:
                            cui_choice = int(input("请选择菜系 (输入编号): "))
                            if cui_choice == len(cuisines) + 1:
                                break
                            elif 1 <= cui_choice <= len(cuisines):
                                self.display_menu("cuisine", cuisines[cui_choice-1])
                            else:
                                print("无效的选择，请重新输入")
                        except ValueError:
                            print("请输入有效的数字")
                elif 1 <= cat_choice <= len(categories):
                    self.display_menu("category", categories[cat_choice-1])
                else:
                    print("无效的选择，请重新输入")
                    continue
            except ValueError:
                print("请输入有效的数字")
                continue

            # 选择菜品
            try:
                item_id = input("请输入要添加的菜品编号 (输入0返回上一级，输入q查看购物车): ")
                if item_id == '0':
                    continue
                if item_id.lower() == 'q':
                    self.view_cart()
                    continue
                    
                item_id = int(item_id)
                selected_item = next((item for item in self.menu if item.id == item_id), None)
                
                if not selected_item:
                    print("没有找到该菜品")
                    continue
                    
                quantity = int(input(f"请输入{selected_item.name}的数量: "))
                if quantity <= 0:
                    print("数量必须大于0")
                    continue
                    
                self.current_order.add_item(selected_item, quantity)
                print(f"已添加 {selected_item.name} x {quantity} 到购物车")
                
            except ValueError:
                print("请输入有效的数字")
                continue

    def view_cart(self):
        """查看购物车"""
        print("\n===== 购物车 =====")
        self.current_order.display_order()
        
        if not self.current_order.items:
            return
            
        print("\n1. 继续点餐")
        print("2. 修改订单")
        print("3. 去结算")
        print("4. 清空购物车")
        
        try:
            choice = int(input("请选择操作: "))
            if choice == 1:
                return
            elif choice == 2:
                self.modify_order()
            elif choice == 3:
                self.checkout()
            elif choice == 4:
                self.clear_cart()
            else:
                print("无效的选择")
        except ValueError:
            print("请输入有效的数字")

    def modify_order(self):
        """修改订单"""
        if not self.current_order.items:
            print("您的订单是空的，无法修改")
            return
            
        self.current_order.display_order()
        try:
            item_index = int(input("请输入要修改的菜品序号 (输入0取消): ")) - 1
            if item_index == -1:
                return
            if 0 <= item_index < len(self.current_order.items):
                item = self.current_order.items[item_index]
                print(f"您选择了 {item.menu_item.name}")
                print("1. 修改数量")
                print("2. 删除该菜品")
                choice = int(input("请选择操作: "))
                
                if choice == 1:
                    quantity = int(input("请输入新的数量: "))
                    self.current_order.update_quantity(item.menu_item.id, quantity)
                    print("数量已更新")
                elif choice == 2:
                    self.current_order.remove_item(item.menu_item.id)
                    print("菜品已删除")
                else:
                    print("无效的选择")
            else:
                print("无效的序号")
        except ValueError:
            print("请输入有效的数字")

    def clear_cart(self):
        """清空购物车"""
        confirm = input("确定要清空购物车吗? (y/n): ")
        if confirm.lower() == 'y':
            self.current_order = Order()
            print("购物车已清空")

    def checkout(self):
        """结算流程"""
        if not self.current_order.items:
            print("您的订单是空的，无法结算")
            return
            
        self.current_order.display_order()
        confirm = input("确认结算吗? (y/n): ")
        if confirm.lower() != 'y':
            print("已取消结算")
            return
            
        self.payment()

    def payment(self):
        """支付流程"""
        total_amount = self.current_order.get_total()
        print("\n===== 支付 =====")
        print(f"订单总金额: ¥{total_amount:.2f}")
        
        # 选择支付方式
        self.payment_system.list_payment_methods()
        try:
            pay_choice = int(input("请选择支付方式 (输入编号): "))
            
            # 调用支付系统处理支付
            payment_success = self.payment_system.process_payment(
                total_amount, 
                self.current_order.order_number, 
                pay_choice
            )
            
            if payment_success:
                # 支付成功处理
                self.current_order.status = "已支付"
                self.current_order.payment_method = self.payment_system.payment_methods[pay_choice]["name"]
                self.current_order.payment_time = datetime.now()
                self.order_history.append(self.current_order)
                
                print("\n===== 支付成功 =====")
                print(f"订单号: {self.current_order.order_number}")
                print(f"支付方式: {self.current_order.payment_method}")
                print(f"支付时间: {self.current_order.payment_time.strftime('%Y-%m-%d %H:%M:%S')}")
                print(f"订单总金额: ¥{total_amount:.2f}")
                print("感谢您的购买，祝您用餐愉快！")
                
                # 重置订单
                self.current_order = Order()
            else:
                print("\n支付未完成，请重新尝试")
                
        except ValueError:
            print("请输入有效的数字")

    def view_order_history(self):
        """查看订单历史"""
        if not self.order_history:
            print("暂无订单历史")
            return
            
        print("\n===== 订单历史 =====")
        for i, order in enumerate(reversed(self.order_history), 1):
            print(f"{i}. 订单号: {order.order_number}")
            print(f"   时间: {order.create_time.strftime('%Y-%m-%d %H:%M')}")
            print(f"   状态: {order.status}")
            print(f"   支付方式: {order.payment_method or '未支付'}")
            print(f"   金额: ¥{order.get_total():.2f}")
            
            # 查看订单详情选项
            if input("   查看详情? (y/n): ").lower() == 'y':
                order.display_order()

    def run(self):
        """运行应用程序"""
        print("===== 欢迎使用环球美食点餐系统 =====")
        while True:
            print("\n主菜单:")
            print("1. 浏览菜单并点餐")
            print("2. 查看购物车")
            print("3. 查看订单历史")
            print("4. 查看支付账户信息")
            print("5. 退出系统")
            
            try:
                choice = int(input("请选择操作 (输入编号): "))
                if choice == 1:
                    self.order_food()
                elif choice == 2:
                    self.view_cart()
                elif choice == 3:
                    self.view_order_history()
                elif choice == 4:
                    # 显示支付账户信息
                    print("\n===== 支付账户信息 =====")
                    self.payment_system.list_payment_methods()
                    try:
                        method_choice = int(input("请选择要查看的支付账户: "))
                        if method_choice in self.payment_system.payment_methods:
                            account_id = self.payment_system.payment_methods[method_choice]["account_id"]
                            account = self.payment_system.get_account(account_id)
                            if account:
                                print(f"\n账户类型: {self.payment_system.payment_methods[method_choice]['name']}")
                                print(f"账户尾号: ****{account_id[-4:]}")
                                account.display_balance()
                                account.display_transaction_history()
                    except ValueError:
                        print("请输入有效的数字")
                elif choice == 5:
                    print("感谢使用，再见！")
                    break
                else:
                    print("无效的选择，请重新输入")
            except ValueError:
                print("请输入有效的数字")


if __name__ == "__main__":
    app = RestaurantApp()
    app.run()